<script>
import CountBox from "@/components/CountBox.vue"
import TarBar from "@/components/TarBar.vue"
import {urlResolve} from "@/utils/urlResolve"
import SafeBox from "@/components/SafeBox.vue"
import {getSafeAreaInsets} from '@/utils/safeAreaInsets'
import {setCartTotal} from "@/utils/storage"
import {clearCartApi, getCartListApi, updateCartApi} from "@/api/cart"
import debounce from "lodash.debounce"

export default {
  name: "Cart",
  components: {
    SafeBox,
    TarBar,
    CountBox
  },
  data() {
    return {
      isEdit: false, // 是否编辑状态
      cartList: [], // 购物车商品列表
    }
  },
  // 每次访问购物车都重新加载数据，因为小程序会缓存页面
  onShow() {
    this.getCartList() // 获取购物车
  },
  computed: {
    // 全选框是否被选中
    isAllChecked() {
      return this.cartTotal === this.selectedCartTotal
    },
    // 购物车商品总数
    cartTotal() {
      const num = this.cartList.reduce((sum, item) => {
        return sum + item.goods_num
      }, 0)
      setCartTotal(num) // 存入本地存储，虽然这样不合法，但是这是最容易实现的效果
      return num
    },

    // 被选中的购物车商品列表
    selectedCartList() {
      return this.cartList.filter(item => item.isChecked) // 从原数组把那些 isChecked 为 false 的过滤掉
    },

    // 被选中购物车商品的总数
    selectedCartTotal() {
      return this.selectedCartList.reduce((sum, item) => {
        return sum + item.goods_num
      }, 0)
    },

    // 被选中购物车商品的总价
    selectedCartPrice() {
      return this.selectedCartList.reduce((sum, item) => {
        return sum + item.goods.goods_price_min * item.goods_num
      }, 0).toFixed(2)
    }
  },
  methods: {
    getSafeAreaInsets,
    // 请求后端cartList数据
    async getCartList() {
      const res = await getCartListApi()

      const arr = res.data.list // 拿到请求的cartList数组

      arr.forEach(item => {
        item.isChecked = false
      })

      this.cartList = arr
    },

    debounceUpdateCart: debounce(function (obj) {
      updateCartApi(obj)
    }, 500),

    // 更新对应 id 的商品的数量，所以需要拿到对应商品的数量 num ,obj 是 商品id，商品数量，商品SKU
    async updateCart(obj) {
      const {num, goods_id, goods_sku_id} = obj

      // 前端更新，再更新后端
      const curCart = this.cartList.find(item => item.goods_id === goods_id)
      curCart.goods_num = num

      // 后端更新
      this.debounceUpdateCart({goodsId: goods_id, goodsNum: num, goodsSkuId: goods_sku_id})
    },

    // 切换小选框
    onToggleSmallChecked(id) {
      const obj = this.cartList.find(item => item.goods_id === id)
      obj.isChecked = !obj.isChecked
    },

    // 切换全选框
    onToggleAllChecked(isAllChecked) {
      this.cartList.forEach(item => item.isChecked = !isAllChecked)
    },

    // 删除购物车被选中的商品
    async onClearCart() {
      // 被选中商品为 0 直接return
      if (!this.selectedCartTotal) return

      const selectedCartList = this.selectedCartList
      const cartIds = selectedCartList.map(item => item.id) // 把原本数组里的商品对象替换成 id

      await clearCartApi(cartIds) // 更新后端

      // 重新从后端拉取数据更新前端
      // 这最后加个await其实还有个好处，async返回的是promise，最后的这个重新拉取会成功后async再return
      await this.getCartList()

      uni.showToast({icon: "none", title: '删除成功'})

      this.isEdit = false // 删除商品后关闭编辑模式
    },

    // 跳转支付页
    goCheckout() {
      if (this.selectedCartTotal <= 0) return

      const query = urlResolve({
        mode: 'cart',
        cartIds: this.selectedCartList.map(item => item.id).join(',')
      })

      uni.navigateTo({url: `/pagesOrders/pages/Checkout/Checkout?${query}`})
    }
  }
}
</script>

<template>
  <div class="cart">

    <van-nav-bar title="购物车"/>

    <view class="cart-container" :style="{height: `calc(100vh - 96px - ${getSafeAreaInsets()})`}">
      <div v-if="cartTotal > 0">
        <!-- 购物车开头 -->
        <div class="cart-title">

          <span class="all">共<text>{{ cartTotal }}</text>件商品</span>

          <span @click="isEdit = !isEdit" class="edit">
					<van-icon name="edit"/>
					编辑
				</span>

        </div>

        <!-- 购物车列表 -->
        <div class="cart-list">

          <div class="cart-item" v-for="item in cartList" :key="item.goods_id">

            <van-checkbox @tap="onToggleSmallChecked(item.goods_id)" :value="item.isChecked"></van-checkbox>

            <div @click="uni.navigateTo({url: `/pages/Product/Product?id=${item.goods_id}`})" class="show">
              <image :src="item.goods.goods_image" alt=""/>
            </div>

            <div class="info">
              <text class="tit text-ellipsis-2">{{ item.goods.goods_name }}</text>
              <div class="bottom">
                <div class="price">¥
                  <text>{{ item.goods.goods_price_min }}</text>
                </div>

                <!--修改购物车商品 num 是要更新商品数量的值，obj是要更新商品的数据，也就是一个商品对象-->
                <CountBox
                    @input="(num) => updateCart({num, goods_id: item.goods_id, goods_sku_id: item.goods_sku_id})"
                    :value="item.goods_num"></CountBox>
              </div>
            </div>

          </div>

        </div>

        <div class="footer-fixed" style="bottom: 50px;">

          <view class="footer-container">
            <div @click="onToggleAllChecked(isAllChecked)" class="all-check">
              <van-checkbox :value="isAllChecked" icon-size="18"></van-checkbox>
              全选
            </div>

            <div class="all-total">
              <div class="price">
                <span>合计：</span>
                <span>¥ <text class="totalPrice">{{ selectedCartPrice }}</text></span>
              </div>
              <!--如果 selectedCartTotal 为 0，那说明没有被选中的商品，那按钮自然得变成灰色-->
              <div v-if="!isEdit" :class="{disabled: !selectedCartTotal}" @click="goCheckout" class="goPay">
                结算({{ selectedCartTotal }})
              </div>
              <div v-else @click="onClearCart" :class="{disabled: !selectedCartTotal}" class="delete">删除</div>
            </div>
          </view>

          <SafeBox></SafeBox>
        </div>
      </div>

      <!--空购物车-->
      <div v-else class="empty-cart">
        <image src="@/static/empty.png" alt=""/>
        <div class="tips">
          您的购物车是空的, 快去逛逛吧
        </div>
        <div class="btn" @click="uni.switchTab({url: '/pages/index/index'})">去逛逛</div>
      </div>

    </view>

    <TarBar tabbar-index="2"></TarBar>
  </div>

</template>

<style lang="less">
// 主题 padding
.cart {
  background-color: #f5f5f5;
  min-height: 100vh;

  .van-nav-bar {
    position: sticky;
    top: 0;
    width: 100%;
  }
}

.cart-container {
  display: flex;
}

.cart-container {
  .cart-title {
    height: 40px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0 10px;
    font-size: 14px;

    .all {
      text {
        font-style: normal;
        margin: 0 2px;
        color: #fa2209;
        font-size: 16px;
      }
    }

    .edit {
      .van-icon {
        font-size: 18px;
      }
    }
  }

  .cart-item {
    margin: 0 10px 10px 10px;
    height: 120px;
    padding: 10px;
    display: flex;
    justify-content: space-between;
    background-color: #ffffff;
    border-radius: 5px;

    .van-checkbox {
      height: 100%;
    }

    .show {
      display: flex;
      align-items: center;

      image {
        width: 80px;
        height: 80px;
      }
    }

    .info {
      width: 210px;
      padding: 10px 5px;
      font-size: 14px;
      display: flex;
      flex-direction: column;
      justify-content: space-between;

      .bottom {
        display: flex;
        justify-content: space-between;

        .price {
          display: flex;
          align-items: flex-end;
          color: #fa2209;
          font-size: 12px;

          text {
            font-size: 16px;
          }
        }
      }
    }
  }
}

.cart-container {
  .empty-cart {
    flex: 1;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;

    image {
      width: 140px;
      height: 92px;
    }

    .tips {
      margin: 30px 0;
      color: #666;
    }

    .btn {
      width: 110px;
      height: 32px;
      line-height: 32px;
      text-align: center;
      background-color: #fa2c20;
      border-radius: 16px;
      color: #fff;
    }
  }
}

.footer-fixed {
  position: fixed;
  left: 0;
  width: 100%;
  border-bottom: 1px solid #ccc;
  background-color: #fff;

  .footer-container {
    height: 50px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0 10px;
    font-size: 14px; // 文字也会响应式

    .all-check {
      display: flex;
      align-items: center;

      .van-checkbox {
        margin-right: 5px;
      }
    }

    .all-total {
      display: flex;
      align-items: center;

      .price {
        font-size: 14px;
        margin-right: 10px;

        .totalPrice {
          color: #fa2209;
          font-size: 18px;
          font-style: normal;
        }
      }

      .goPay,
      .delete {
        min-width: 100px;
        height: 36px;
        line-height: 36px;
        text-align: center;
        background-color: #fa2f21;
        color: #fff;
        border-radius: 18px;

        &.disabled {
          background-color: #ff9779;
        }
      }
    }
  }
}


</style>
